package com.per.demobeetlsql.aspect;

import com.per.demobeetlsql.datasource.DbContextHolder;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Cheng
 * @date 2020/9/24 16:07
 */
@Aspect
@Component
public class DataSourceAspect {

    /**
     * 根据datasource参数的值设置不同的DataSource
     */
    @Before("execution(* com.per.demobeetlsql.service.*.*(..))")
    public void changeDataSource(JoinPoint joinPoint) throws Exception {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Class<?> clazz = joinPoint.getTarget().getClass();

        ParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
        String[] parameterNames = discoverer.getParameterNames(clazz.getDeclaredMethod(methodSignature.getName(),
                methodSignature.getParameterTypes()));

        Object[] args = joinPoint.getArgs();
        Map<String, Object> paramsMap = new HashMap<>();
        for (int i = 0; i < parameterNames.length; i++) {
            String key = parameterNames[i];
            Object value = args[i];
            paramsMap.put(key, value);
        }

        String dbCode = null;

        if (paramsMap.containsKey("datasource")) {
            dbCode = (String) paramsMap.get("datasource");
        }

        if (DbContextHolder.getDataSourceKey() == null) {
            if (dbCode != null) {
                DbContextHolder.setDataSourceKey(dbCode);
            }
        }
    }

    /**
     * 方法执行完之后清除当前数据源，让其使用默认数据源
     */
    @After("execution(* com.per.demobeetlsql.service.*.*(..))")
    public void restoreDataSource() {
        DbContextHolder.clearDataSourceKey();
    }
}
